﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;

namespace ObjectOuster
{
    #region Delegates
    public delegate void MakeMoveDelegate(int theColumn,int theRow);
    public delegate void NewGameDelegate();
    public delegate void UndoMoveDelegate();
    #endregion
    public static class GameData
    {
        #region Constants
        public const int BoardWidth = 20;
        public const int BoardHeight = 15;
        public const int ScorePerEmptyRow = 25;
        public const int ScorePerEmptyColumn = 100;
        #endregion

        #region Events
        private static event NewGameDelegate onNewGame;
        private static event MakeMoveDelegate onMakeMove;
        private static event UndoMoveDelegate onUndoMove;
        public static event MakeMoveDelegate OnMakeMove
        {
            add
            {
                onMakeMove += value;
            }
            remove
            {
                onMakeMove -= value;
            }
        }
        public static event NewGameDelegate OnNewGame
        {
            add
            {
                onNewGame += value;
            }
            remove
            {
                onNewGame -= value;
            }
        }
        public static event UndoMoveDelegate OnUndoMove
        {
            add
            {
                onUndoMove += value;
            }
            remove
            {
                onUndoMove -= value;
            }
        }
        #endregion

        #region Properties
        private static bool firstGame = true;
        private static int score = 0;
        private static Stack<int> scoreStack = new Stack<int>();
        private static int highScore = 0;
        public static int TotalScore
        {
            get
            {
                return Score + Board.EmptyColumns * ScorePerEmptyColumn + Board.EmptyRows * ScorePerEmptyRow;
            }
        }
        public static int Score
        {
            get
            {
                return score;
            }
            set
            {
                if (value != score)
                {
                    if (value > score)
                    {
                        scoreStack.Push(score);
                    }
                    score = value;
                }
            }
        }
        public static int HighScore
        {
            get
            {
                return (TotalScore > highScore) ? (TotalScore) : (highScore);
            }
            set
            {
                highScore = value;
            }
        }
        private static Board board = new Board(BoardWidth, BoardHeight);
        public static Board Board
        {
            get
            {
                return board;
            }
        }
        #endregion
        
        #region Random Board Generation
        private static Random random = new Random();
        private static BoardCellState[] table = new BoardCellState[] { BoardCellState.First, BoardCellState.Second, BoardCellState.Third, BoardCellState.Fourth, BoardCellState.Fifth, BoardCellState.Sixth };
        private static BoardCellState RandomCellState
        {
            get
            {
                return table[random.Next(table.Length)];
            }
        }
        #endregion

        #region Game Mechanics
        public static void MakeMove(int theColumn, int theRow)
        {
            int score = Board.MakeMove(theColumn, theRow);
            Score += (score - 1) * (score) / 2;
            Board.CleanUpBoard();
            if (Board.MovesLeft == 0)
            {
                GameConfig.SoundEffects.Play(SoundEffect.NoMovesLeft);
            }
            else
            {
                switch (score)
                {
                    case 0:
                        break;
                    default:
                        if (onMakeMove != null)
                        {
                            onMakeMove(theColumn, theRow);
                        }
                        break;
                }
            }
        }
        public static void NewGame()
        {
            if (!firstGame)
            {
                HighScore = HighScore;
            }
            firstGame = false;
            Board.Clear();
            scoreStack.Clear();
            Score = 0;
            for (int column=0; column < Board.Columns; ++column)
            {
                for (int row = 0; row < Board.Rows; ++row)
                {
                    Board[column][row].State = RandomCellState;
                }
            }
            Board.MarkRegions();
            if (onNewGame != null)
            {
                onNewGame();
            }
        }
        public static void UndoMove()
        {
            if (scoreStack.Count > 0)
            {
                Board.HighlightedRegion = -1;
                Score = scoreStack.Pop();
                Board.UndoMove();
                if (onUndoMove != null)
                {
                    onUndoMove();
                }
            }
        }
        #endregion
    }
}
